spb/internetpressure
Public
TypeScript 36.3%
Python 31.8%
Go 18%
JavaScript 9.8%
Shell 1.9%
SQL 1.4%
CSS 0.5%
1import type { Metadata } from 'next';2import Link from 'next/link';3import { notFound } from 'next/navigation';4import { LargestGrid, MonthStrip, TopEvents, TopLists } from '@/components/history/HistoryViews';5import { Section } from '@/components/ui/primitives';6import { apiGet } from '@/lib/api';7import type { HistorySummary } from '@/lib/types';89export const dynamic = 'force-dynamic';1011type Params = Promise<{ year: string }>;1213export async function generateMetadata({ params }: { params: Params }): Promise<Metadata> {14 const { year } = await params;15 return { title: `History ${year}`, description: `Global Internet Pressure in ${year}: months, largest events, most affected networks and regions.` };16}1718export default async function HistoryYearPage({ params }: { params: Params }) {19 const { year } = await params;20 if (!/^\d{4}$/.test(year)) notFound();21 const s = await apiGet<HistorySummary>(`/api/v1/history/summary?year=${year}`);22 return (23 <div className="pb-8">24 <header className="pt-6 pb-4">25 <p className="label">26 <Link href="/history" className="hover:text-ink">27 History28 </Link>{' '}29 · year30 </p>31 <h1 className="num mt-1 text-[26px] font-medium tracking-tight sm:text-[32px]">{year}</h1>32 </header>33 <Section label="Months">34 <MonthStrip months={s.months ?? []} />35 </Section>36 <Section label="Largest events">37 <LargestGrid largest={s.largest} />38 </Section>39 <TopLists s={s} />40 <Section label="Top events">41 <TopEvents events={s.top_events} />42 </Section>43 </div>44 );45}46